home *** CD-ROM | disk | FTP | other *** search
/ The Atari Compendium / The Atari Compendium (Toad Computers) (1994).iso / files / prgtools / editors / emcs1857 / 1857sr~1.zoo / src / utils / strip.c < prev   
Encoding:
C/C++ Source or Header  |  1991-09-27  |  13.5 KB  |  593 lines

  1. /*
  2.  *    strip TOS executable format files of symbol table info
  3.  *    usage: strip [-g] [-k] [-l names] files ...
  4.  *
  5.  *    Original version by ++jrb    bammi@dsrgsun.ces.cwru.edu
  6.  *    (i.e. Jwahar Bammi)
  7.  *    Modified to add extra options -g -k and -l by
  8.  *    Michal Jaegermann        ntomczak@ualtavm.bitnet
  9.  *    November 1st, 1990
  10.  *
  11.  *    -g    keep all global symbols
  12.  *    -k    keep _stksize symbol, so stack size can be adjusted
  13.  *        even for nearly-stripped gcc produced executables
  14.  *    -l nms    keep all symbols listed in a file 'nms'
  15.  *
  16.  *    Modified sources compile both with gcc and Sozobon C
  17.  *
  18.  *      Added code to deal correctly with extended symbols produced
  19.  *      by -G option of gcc
  20.  *      Both -k and -l options convert extended symbols into
  21.  *      regular ones.
  22.  *
  23.  *    ++jrb 4/25/91: 
  24.  *    Macroized the code to take care of WORD_ALIGNED cross environments.
  25.  *    Minor fixes for a !atari !gcc compiler.   
  26.  */
  27. #include <stdio.h>
  28. #ifdef atarist
  29. #ifdef __GNUC__
  30. #  include <stddef.h>
  31. #  include <memory.h>
  32. #  include <unixlib.h>
  33. #else
  34. #include <malloc.h>
  35. extern long lread();
  36. extern long lwrite();
  37. extern long lseek();
  38. #endif
  39. #endif
  40.  
  41. #ifdef unix
  42. #  include <strings.h>
  43. #  define lwrite write
  44. #  define lread  read
  45.    extern char *malloc(), *realloc();
  46. #else
  47. #  include <string.h>
  48. #endif
  49.  
  50. #include <fcntl.h>
  51.  
  52. #ifdef __GNUC__
  53. #define NULL        ((void *)0)
  54. #endif
  55. #define NEWBUFSIZ    16384L
  56.  
  57. char            mybuf[NEWBUFSIZ];
  58. char            tmpname[128];
  59.  
  60. #define SYMLEN 8
  61.  
  62. typedef char    symstr_t[SYMLEN];
  63. symstr_t        stklist[] = {{'_', '_', 's', 't', 'k', 's', 'i', 'z',},
  64.                  {'\0'}};
  65.  
  66. #ifdef atarist
  67. long            _stksize = 1L;
  68. #endif
  69.  
  70. #ifndef __PROTO
  71. #  if __STDC__ || __cplusplus
  72. #   define __PROTO(s) s
  73. #  else
  74. #   define __PROTO(s) ()
  75. #  endif
  76. #endif
  77.  
  78. void usage __PROTO((char *s ));
  79. int main __PROTO((int argc , char **argv ));
  80. int strip __PROTO((    char *name,
  81.         symstr_t *nmlist,
  82.         long (*select )(int ,int ,long ,symstr_t *)));
  83. long copy __PROTO((int from , int to , long bytes ));
  84. void report __PROTO((char *s ));
  85. symstr_t *mklist __PROTO((char *fname ));
  86. long sel_globs __PROTO((int fd , int tfd , long sbytes , symstr_t *nmlist ));
  87. long sel_listed __PROTO((int fd , int tfd , long sbytes , symstr_t *nmlist ));
  88. extern char    *getenv __PROTO((const char *));
  89.  
  90. int 
  91. main (argc, argv)
  92.     int             argc;
  93.     char          **argv;
  94. {
  95.     int             status = 0;
  96.     int             flag = -1;
  97.     symstr_t       *nmlist = (symstr_t *) 0;
  98.     long            (*select) __PROTO((int, int, long, symstr_t *));
  99. #ifdef atarist
  100.     char           *tmpdir;
  101.     register int    l;
  102. #endif
  103.  
  104.     select = (long (*) __PROTO((int, int, long, symstr_t *))) 0;
  105.     /* process arguments */
  106.     while (argv++, --argc) {
  107.     if ('-' != **argv)
  108.         break;
  109.     (*argv)++;
  110.     if ((-1) != flag)
  111.         usage ("only one option at a time is accepted\r\n");
  112.     flag = **argv;
  113.     switch (flag) {
  114.     case 'g':
  115.         select = sel_globs;
  116.         break;
  117.     case 'k':
  118.         nmlist = stklist;
  119.         select = sel_listed;
  120.         break;
  121.     case 'l':
  122.         (*argv)++;
  123.         if ('\0' == **argv) {
  124.         --argc;
  125.         argv++;
  126.         }
  127.         if ((symstr_t *) 0 == (nmlist = mklist (*argv)))
  128.         usage ("cannot create a list of reserved names\r\n");
  129.         select = sel_listed;
  130.         break;
  131.     default:
  132.         usage ("");
  133.         break;
  134.     }
  135.     }
  136.  
  137.     if (argc < 1) {
  138.     usage ("");
  139.     }
  140.  
  141. #ifdef __GNUC__
  142. #ifdef atarist
  143.     tmpname[0] = '\0';
  144.     if ((tmpdir = getenv ("TEMP")) != NULL) {
  145.     strcpy (tmpname, tmpdir);
  146.     l = (int) strlen (tmpname) - 1;
  147.     if (tmpname[l] == '\\')
  148.         tmpname[l] = '\0';
  149.     }
  150.     strcat (tmpname, "\\STXXXXXX");
  151. #else
  152.     strcpy (tmpname, "/tmp/STXXXXXX");
  153. #endif
  154.  
  155.     mktemp (tmpname);
  156. #else /* not __GNUC__ */
  157. #  ifdef atarist
  158.     if ((tmpdir = getenv ("TEMP")) != NULL) {
  159.     strcpy (tmpname, tmpdir);
  160.     l = (int) strlen (tmpname) - 1;
  161.     if (tmpname[l] != '\\') {
  162.         l++;
  163.         tmpname[l] = '\\';
  164.     }
  165.     l++;
  166.     }
  167.     else {
  168.     l = 0;
  169.     }
  170.     tmpnam (&tmpname[l]);
  171. #  else
  172.     strcpy (tmpname, "/tmp/STXXXXXX");
  173.     mktemp(tmpname);
  174. #  endif    
  175. #endif /* __GNUC__ */
  176.     do {
  177.     status |= strip (*argv++, nmlist, select);
  178.     } while (--argc > 0);
  179.  
  180.     unlink (tmpname);
  181.     return status;
  182. }
  183.  
  184. void
  185. usage (s)
  186.     char           *s;
  187. {
  188.     report (s);
  189.     report ("Usage: strip [-k] [-l names] [-g] files ...\r\n");
  190.     exit (1);
  191. }
  192.  
  193. #if (defined(__GNUC__)) && (!defined(unix))
  194. #include <st-out.h>
  195. #else
  196. /* include relevant fragments of <st-out.h> file directly */
  197.  
  198. struct aexec {
  199.      short    a_magic;    /* magic number */
  200. unsigned long    a_text;        /* size of text segment */
  201. unsigned long    a_data;        /* size of initialized data */
  202. unsigned long    a_bss;        /* size of uninitialized data */
  203. unsigned long    a_syms;        /* size of symbol table */
  204. unsigned long    a_AZero1;    /* always zero */
  205. unsigned long    a_AZero2;    /* always zero */
  206. unsigned short    a_isreloc;    /* is reloc info present */
  207. };
  208. #define    CMAGIC    0x601A        /* contiguous text */
  209.  
  210. #define    A_BADMAG(x)     (((x).a_magic)!=CMAGIC)
  211.  
  212. /*
  213.  * Format of a symbol table entry
  214.  */
  215. struct    asym 
  216.     {
  217.     char        a_name[SYMLEN];    /* symbol name */
  218.     unsigned short    a_type;        /* type flag   */
  219.     unsigned long    a_value;    /* value of this symbol
  220.                        (or sdb offset) */
  221.     };
  222.  
  223. #define A_GLOBL    0x2000        /* global */
  224. #define A_LNAM  0x0048        /* extended name */
  225.  
  226. #endif /* __GNUC__ */
  227.  
  228. #if !__STDC__ && !__cplusplus
  229. #  ifndef offsetof
  230. #    define offsetof(TYPE, MEMBER) ((unsigned long) &((TYPE *)0)->MEMBER)
  231. #  endif
  232.    typedef unsigned long size_t;
  233. #endif
  234.  
  235. #ifdef WORD_ALIGNED
  236. # define SIZEOF_AEXEC ((2*sizeof(short)) + (6*sizeof(long)))
  237. # define SIZEOF_ASYM  ((SYMLEN*sizeof(char)) + sizeof(short) + sizeof(long))
  238. # define SYM_OFFSET   (sizeof(short) + (3*sizeof(long)))
  239.   int read_head __PROTO((int fd, struct aexec *a));
  240. #else
  241. # define SIZEOF_AEXEC (sizeof(struct aexec))
  242. # define SIZEOF_ASYM  (sizeof(struct asym))
  243. # define SYM_OFFSET   (offsetof (struct aexec, a_syms))
  244. #endif
  245.  
  246. int 
  247. strip (name, nmlist, select)
  248. char *name;
  249. symstr_t * nmlist;
  250. long (*select) __PROTO((int, int, long, symstr_t *));
  251. {
  252.     register int    fd;
  253.     register int    tfd;
  254.     register long   count, rbytes, sbytes;
  255.     long            lbytes;
  256.     struct aexec    ahead;
  257.  
  258.     if ((fd = open (name, O_RDONLY, 0666)) < 0) {
  259.     perror (name);
  260.     return 2;
  261.     }
  262.     if ((tfd = open (tmpname, O_WRONLY | O_TRUNC | O_CREAT, 0644)) < 0) {
  263.     perror (tmpname);
  264.     close (fd);
  265.     return 4;
  266.     }
  267. #ifndef WORD_ALIGNED
  268.     if ((count = lread (fd, &ahead, (long) sizeof (ahead))) 
  269.                     != (long) sizeof (ahead)) {
  270. #else
  271.     if (read_head (fd, &ahead)) {
  272. #endif
  273.     perror (name);
  274.     close (tfd);
  275.     close (fd);
  276.     return 8;
  277.     }
  278.     if (A_BADMAG (ahead)) {
  279.     report (name);
  280.     report (": Bad Magic number\r\n");
  281.     close (tfd);
  282.     close (fd);
  283.     return 0x10;
  284.     }
  285.     sbytes = ahead.a_syms;
  286.     if (0L == sbytes) {
  287.     report (name);
  288.     report (": Already Stripped\r\n");
  289.     close (tfd);
  290.     close (fd);
  291.     return 0x20;
  292.     }
  293.     if (lseek (fd, 0L, 0) < 0) {
  294.     report (name);
  295.     report (": seek error\r\n");
  296.     close (tfd);
  297.     close (fd);
  298.     return 0x40;
  299.     }
  300.     count = SIZEOF_AEXEC + ahead.a_text + ahead.a_data;
  301.     if (copy (fd, tfd, count) != count) {
  302.     close (tfd);
  303.     close (fd);
  304.     return 0x80;
  305.     }
  306.     if ((long(*)())0 == select) {     /* remove whole symbol table */
  307.     lbytes = 0L;
  308.     if (lseek (fd, sbytes, 1) < 0) {
  309.         report (name);
  310.         report (": seek error\r\n");
  311.         close (tfd);
  312.         close (fd);
  313.         return 0x100;
  314.     }
  315.     }
  316.     else {
  317.     lbytes = ( *select )(fd, tfd, sbytes, nmlist);
  318.     }
  319.     if ((rbytes = copy (fd, tfd, 0x7fffffffL)) < 0) {
  320.     close (tfd);
  321.     close (fd);
  322.     return 0x200;
  323.     }
  324.     if (lseek (tfd, (long)(SYM_OFFSET), 0) < 0) {
  325.     close (tfd);
  326.     close (fd);
  327.     return 0x400;
  328.     }
  329.     if (lwrite (tfd, &lbytes, (long)sizeof (lbytes)) != 
  330.                         (long) sizeof (lbytes)) {
  331.     close (tfd);
  332.     close (fd);
  333.     return 0x800;
  334.     }
  335.     close (tfd);
  336.     close (fd);
  337.     if (rename(tmpname, name) == 0) return 0; /* try to rename it */
  338.     if ((fd = open (name, O_WRONLY | O_TRUNC | O_CREAT, 0666)) < 0) {
  339.     perror (name);
  340.     return 0x1000;
  341.     }
  342.     if ((tfd = open (tmpname, O_RDONLY, 0666)) < 0) {
  343.     perror (tmpname);
  344.     close (fd);
  345.     return 0x2000;
  346.     }
  347.  
  348.     count = SIZEOF_AEXEC + ahead.a_text + ahead.a_data + rbytes + lbytes;
  349.     if (copy (tfd, fd, count) != count) {
  350.     close (tfd);
  351.     close (fd);
  352.     return 0x4000;
  353.     }
  354.     close (tfd);
  355.     close (fd);
  356.     return 0;
  357. }
  358.  
  359. /*
  360.  * copy from, to in NEWBUFSIZ chunks upto bytes or EOF whichever occurs first
  361.  * returns # of bytes copied
  362.  */
  363. long 
  364. copy (from, to, bytes)
  365. int from, to;
  366. long bytes;
  367. {
  368.     register long   todo, done = 0L, remaining = bytes, actual;
  369.  
  370.     while (done != bytes) {
  371.     todo = (remaining > NEWBUFSIZ) ? NEWBUFSIZ : remaining;
  372.     if ((actual = lread (from, mybuf, todo)) != todo) {
  373.         if (actual < 0) {
  374.         report ("Error Reading\r\n");
  375.         return -done;
  376.         }
  377.     }
  378.     if (lwrite (to, mybuf, actual) != actual) {
  379.         report ("Error Writing\r\n");
  380.         return -done;
  381.     }
  382.     done += actual;
  383.     if (actual != todo)    /* eof reached */
  384.         return done;
  385.     remaining -= actual;
  386.     }
  387.     return done;
  388. }
  389.  
  390. void 
  391. report (s)
  392. char * s;
  393. {
  394.     lwrite (2, s, (long) strlen (s));
  395. }
  396.  
  397. /*
  398.  * Given a name of a file with reserved symbols create an array of
  399.  * reserved symbol names.  To terminate create an entry which starts
  400.  * with a null character.
  401.  */
  402.  
  403. #define LBUFSIZE 128
  404. #define NMSTEP 10
  405.  
  406. symstr_t       *
  407. mklist (fname)
  408. char * fname;
  409. {
  410.     FILE           *fp;
  411.     symstr_t       *list = (symstr_t *) 0;
  412.     int             left = 0;
  413.     int             pos = 0;
  414.     int             i;
  415.     size_t          max_size = 1;
  416.     char            lbuf[LBUFSIZE];
  417.     char           *in, *out;
  418.  
  419.     if (NULL == (fp = fopen (fname, "r"))) {
  420.     report (fname);
  421.     report (" -- ");
  422.     usage ("cannot open this file\r\n");
  423.     }
  424.  
  425.     while (NULL != fgets (lbuf, LBUFSIZE, fp)) {
  426.     if (0 == left) {
  427.         max_size += NMSTEP;
  428.         if ((symstr_t *)0 == list) {
  429.         list = (symstr_t *) malloc ( max_size * sizeof (symstr_t));
  430.         }
  431.         else {
  432.         list = (symstr_t *) realloc ((void *) list,
  433.                          max_size * sizeof (symstr_t));
  434.  
  435.         }
  436.         if ((symstr_t *)0 == list) {
  437.         report ("out of memory making symbol list\r\n");
  438.         exit (-3);
  439.         }
  440.         left = NMSTEP;
  441.     }
  442.     /* strip all leading white space */
  443.     in = lbuf;
  444.     while (' ' == *in || '\t' == *in)
  445.         in++;
  446.     if ('\n' == *in)
  447.         continue;        /* empty line - skip it */
  448.     out = &list[pos][0];
  449.     for (i = SYMLEN; i > 0; --i) {
  450.         if ('\n' == *in || ' ' == *in || '\t' == *in) {
  451.         *out = '\0';
  452.         break;
  453.         }
  454.         *out++ = *in++;
  455.     }
  456.     pos++;
  457.     --left;
  458.     }                /* while */
  459.     if ((symstr_t *)0 != list) {
  460.     list[pos][0] = '\0';    /* terminate created list */
  461.     }
  462.     return (list);
  463. }
  464.  
  465. /*
  466.  * From a file handle fd to a file handle tfd copy up to 'sbytes' bytes
  467.  * of a symbol table selecting only those symbols which have A_GLOBL
  468.  * flag set. Table nmlist is not really used, but is here for a uniform
  469.  * interface.  Returns a number of bytes copied.
  470.  */
  471. long
  472. sel_globs (fd, tfd, sbytes, nmlist)
  473. int fd, tfd;
  474. long sbytes;
  475. symstr_t * nmlist;
  476. {
  477.     long            lbytes = 0;
  478.     struct asym     cur_sym;
  479.     int            cont = 0;
  480.  
  481.     while (sbytes) {
  482.     if ((long)SIZEOF_ASYM != lread (fd, &cur_sym, 
  483.                         (long)SIZEOF_ASYM)) {
  484.         report ("error on reading symbol table\r\n");
  485.         break;
  486.     }
  487.     if (0 == cont) { /* if we are not dealing with the second part */
  488.         cont = (0 != (cur_sym.a_type & A_LNAM));
  489.         if (cur_sym.a_type & A_GLOBL) {
  490.         cont = -cont;
  491.         if ((long)SIZEOF_ASYM != lwrite (tfd, &cur_sym,
  492.                             (long)SIZEOF_ASYM)) {
  493.             report ("error on writing symbol table\r\n");
  494.             break;
  495.         }
  496.         lbytes += SIZEOF_ASYM;
  497.         }
  498.     }
  499.     else { /* this was an extended symbol */
  500.         if (cont < 0) {  /* if global then write */
  501.         if ((long)SIZEOF_ASYM != lwrite (tfd, &cur_sym,
  502.                             (long)SIZEOF_ASYM)) {
  503.             report ("error on writing symbol table\r\n");
  504.             break;
  505.         }
  506.         lbytes += SIZEOF_ASYM;
  507.         }
  508.         cont = 0;
  509.     }
  510.     sbytes -= SIZEOF_ASYM;
  511.     }
  512.     return (lbytes);
  513. }
  514.  
  515. /*
  516.  * From a file handle fd to a file handle tfd copy up to 'sbytes' bytes
  517.  * of a symbol table selecting only those symbols which are on nmlist.
  518.  * Free nmlist if different from a default global one.
  519.  * Returns a number of bytes copied.
  520.  */
  521. long
  522. sel_listed (fd, tfd, sbytes, nmlist)
  523. int fd, tfd;
  524. long sbytes;
  525. symstr_t * nmlist;
  526. {
  527.     long            lbytes = 0;
  528.     symstr_t       *kname;
  529.     struct asym     cur_sym, spare;
  530.  
  531.     if ((symstr_t *) 0 == nmlist)
  532.     return (0L);
  533.  
  534.     while (sbytes) {
  535.     if ((long)SIZEOF_ASYM != lread (fd, &cur_sym,
  536.                         (long) SIZEOF_ASYM)) {
  537.         report ("error on reading symbol table\r\n");
  538.         break;
  539.     }
  540.     for (kname = nmlist; '\0' != **kname; kname++) {
  541.         if (0 == strncmp (&(*kname)[0], &cur_sym.a_name[0], SYMLEN)) {
  542.         if (A_LNAM & cur_sym.a_type) { /* if extended */
  543.             cur_sym.a_type ^= A_LNAM;
  544.             if ((long)SIZEOF_ASYM != lread (fd, &spare,
  545.                         (long)SIZEOF_ASYM)) {
  546.             report ("error on reading symbol table\r\n");
  547.             goto leave;  /* skip two loop levels */
  548.             }
  549.             sbytes -= SIZEOF_ASYM;
  550.         }
  551.         if ((long)SIZEOF_ASYM != lwrite (tfd, &cur_sym,
  552.                         (long)SIZEOF_ASYM)) {
  553.             report ("error on writing symbol table\r\n");
  554.             goto leave;
  555.         }
  556.         lbytes += SIZEOF_ASYM;
  557.         break;
  558.         }
  559.     }  /* for */
  560.     sbytes -= SIZEOF_ASYM;
  561.     }  /* while */
  562. leave:
  563.     if (nmlist != stklist) {
  564.     free (nmlist);
  565.     nmlist = (symstr_t *) 0;
  566.     }
  567.     return (lbytes);
  568. }
  569.  
  570. #ifdef WORD_ALIGNED
  571. /*
  572.  * read header -- return !0 on err
  573.  */
  574. #define ck_read(fd, addr, siz) \
  575.   if((long)siz != lread(fd, addr, (long)siz)) return !0;
  576.  
  577. int read_head (fd, a)
  578. int fd;
  579. struct aexec *a;
  580. {
  581.     ck_read(fd, &a->a_magic,   sizeof(a->a_magic));
  582.     ck_read(fd, &a->a_text,    sizeof(a->a_text));
  583.     ck_read(fd, &a->a_data,    sizeof(a->a_data));
  584.     ck_read(fd, &a->a_bss,     sizeof(a->a_bss));
  585.     ck_read(fd, &a->a_syms,    sizeof(a->a_syms));
  586.     ck_read(fd, &a->a_AZero1,  sizeof(a->a_AZero1));
  587.     ck_read(fd, &a->a_AZero2,  sizeof(a->a_AZero2));
  588.     ck_read(fd, &a->a_isreloc, sizeof(a->a_isreloc));
  589.  
  590.     return 0;
  591. }
  592. #endif
  593.